#include "Arduino.h"
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include "LittleFS.h"
#include <DNSServer.h>
 
ESP8266WiFiMulti wifiMulti;         // 建立ESP8266WiFiMulti对象
 
ESP8266WebServer esp8266_server(80);// 建立ESP8266WebServer对象，该对象用于响应HTTP请求。监听端口（80）


const byte DNS_PORT = 53;
IPAddress apIP(192, 168, 1, 1);
DNSServer dnsServer;

WiFiUDP Udp;

const char *APssid = "XK图传-";
const char *APpassword = "12345678";
//const char *STAipUse;

String STAip;
String STAssid;
String STApassword;

bool wifiConfig;
bool LED_Flag = false;
File dataFile;

void handleControl();
void handleUserRequest();
bool handleFileRead(String resource);
String getContentType(String filename);
bool autoConfig();
void htmlConfig();
void send();

#define buttonPin D3            // 按钮引脚D3

void setup() {
  
  pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

  LittleFS.begin();
  //Serial.begin(9600);

  wifiConfig = autoConfig();

  if(wifiConfig == false)
  {
    htmlConfig();
  }
}

void loop() {
  if(wifiConfig == false)
  {
    esp8266_server.handleClient();//处理网络请求
    dnsServer.processNextRequest();
  }
  if(wifiConfig == true)
  {
    send();
  }
}

void handleControl(){
  String ip = esp8266_server.arg("ip"); 
  dataFile = LittleFS.open("/ip.txt", "w");
  dataFile.print(ip);
  dataFile.close();

  String ssid = esp8266_server.arg("ssid");
  dataFile = LittleFS.open("/ssid.txt", "w");
  dataFile.print(ssid);
  dataFile.close();

  String password = esp8266_server.arg("password"); 
  dataFile = LittleFS.open("/password.txt", "w");
  dataFile.print(password);
  dataFile.close();

  handleFileRead("/");

  wifiConfig = autoConfig();
  if(wifiConfig == false)
  {
    htmlConfig();
  }
}

// 处理用户浏览器的HTTP访问
void handleUserRequest(){         

  // 通过handleFileRead函数处处理用户请求资源
  bool fileReadOK = handleFileRead("/");

  // 如果在LittleFS无法找到用户访问的资源，则回复404 (Not Found)
  if (!fileReadOK){                                                 
    esp8266_server.send(404, "text/plain", "404 Not Found"); 
  }
}

bool handleFileRead(String resource){            //处理浏览器HTTP访问

  if (resource.endsWith("/")) {                   // 如果访问地址以"/"为结尾
    resource = "index.html";                     // 则将访问地址修改为/index.html便于LittleFS访问
  } 
  
  String contentType = getContentType(resource);  // 获取文件类型
  
  if (LittleFS.exists(resource)) {                     // 如果访问的文件可以在LittleFS中找到
    File file = LittleFS.open(resource, "r");          // 则尝试打开该文件
    esp8266_server.streamFile(file, contentType);// 并且将该文件返回给浏览器
    file.close();                                // 并且关闭文件
    return true;                                 // 返回true
  }
  return false;                                  // 如果文件未找到，则返回false
}

// 获取文件类型
String getContentType(String filename){
  if(filename.endsWith(".htm")) return "text/html";
  else if(filename.endsWith(".html")) return "text/html";
  else if(filename.endsWith(".css")) return "text/css";
  else if(filename.endsWith(".js")) return "application/javascript";
  else if(filename.endsWith(".png")) return "image/png";
  else if(filename.endsWith(".gif")) return "image/gif";
  else if(filename.endsWith(".jpg")) return "image/jpeg";
  else if(filename.endsWith(".ico")) return "image/x-icon";
  else if(filename.endsWith(".xml")) return "text/xml";
  else if(filename.endsWith(".pdf")) return "application/x-pdf";
  else if(filename.endsWith(".zip")) return "application/x-zip";
  else if(filename.endsWith(".gz")) return "application/x-gzip";
  return "text/plain";
}

bool autoConfig()
{
  STAip="";
  dataFile = LittleFS.open("/ip.txt", "r"); 
  for(int i=0; i<dataFile.size(); i++){
    STAip=STAip+(char)dataFile.read();      
  }
  //Serial.print(STAip);
  //STAipUse = STAip.c_str();  
  dataFile.close();

  STAssid="";
  dataFile = LittleFS.open("/ssid.txt", "r"); 
  for(int i=0; i<dataFile.size(); i++){
    STAssid=STAssid+(char)dataFile.read();      
  }
  //Serial.print(STAssid);  
  dataFile.close();

  STApassword="";
  dataFile = LittleFS.open("/password.txt", "r"); 
  for(int i=0; i<dataFile.size(); i++){
    STApassword=STApassword+(char)dataFile.read();      
  }
  //Serial.print(STApassword);
  dataFile.close();

  WiFi.mode(WIFI_STA);
  WiFi.begin(STAssid.c_str(), STApassword.c_str());
  for (int i = 0; i < 20; i++)
  {
    if (digitalRead(buttonPin) == 0)
    {
      return false;
    }
    if (WiFi.status() == WL_CONNECTED)
    {
      digitalWrite(LED_BUILTIN, HIGH); 
      Serial.setRxBufferSize(10000);
      Serial.begin(2000000);  
      return true;
    }
    else
    {
      LED_Flag = !LED_Flag;
      if(LED_Flag)
          digitalWrite(LED_BUILTIN, HIGH);
      else
          digitalWrite(LED_BUILTIN, LOW); 
      delay(500);
    }
  }
  return false;
}

void htmlConfig()
{
  WiFi.mode(WIFI_AP);//设置Wi-Fi为AP模式
  IPAddress softLocal(192,168,1,1);//设置内网WIFI IP地址
  IPAddress softGateway(192,168,1,1);//设置网关
  IPAddress softSubnet(255,255,255,0);
  WiFi.softAPConfig(softLocal, softGateway, softSubnet);
  WiFi.softAP(APssid+(String)ESP.getChipId(), APpassword);

  dnsServer.start(DNS_PORT, "*", apIP);

  //初始化网络服务器
  esp8266_server.on("/network", handleControl);
  esp8266_server.onNotFound(handleUserRequest);//处理其它网络请求

  // 启动网站服务
  esp8266_server.begin();
}

size_t RxHeadState = 0;
size_t RxTailState = 0;
size_t RxCounter = 0;
size_t counti;
uint8_t sbuf[12000];
//发送函数
void send(){
  if(Serial.available())
  {
    if(RxHeadState == 0&&Serial.read()==0x00)
    {
      RxHeadState = 1;
    }
    else if(RxHeadState == 1&&Serial.read()==0xff)
    {
      RxHeadState = 2;
    }
    else if(RxHeadState == 2&&Serial.read()==0x01)
    {
      RxHeadState = 3;
    }
    else if(RxHeadState == 3&&Serial.read()==0x01)
    {
      RxHeadState = 4;
    }
    else if(RxHeadState == 4)
    {
      sbuf[RxCounter++]=Serial.read();
      if(RxTailState == 0&&sbuf[RxCounter-1]==0x01)
      {
        RxTailState = 1;
      }
      else if(RxTailState == 1&&sbuf[RxCounter-1]==0x01)
      {
        RxTailState = 2;
      }
      else if(RxTailState == 2&&sbuf[RxCounter-1]==0xff)
      {
        RxTailState = 3;
      }
      else if(RxTailState == 3&&sbuf[RxCounter-1]==0x00)
      {

        RxTailState = 4;
      }
      else if(RxCounter>6400)
      {
        if(Serial.available())
        {
          counti = Serial.available();
          Serial.readBytes(sbuf, counti);
        }
        RxHeadState = 0;
        RxTailState = 0;
        RxCounter=0;
      }
      else
      {
        RxTailState = 0;
      }
    }
    else
    {
      if(Serial.available())
      {
        counti = Serial.available();
        Serial.readBytes(sbuf, counti);
      }
      RxHeadState = 0;
    }
  }
  if(RxTailState == 4)
  {
    counti=RxCounter-4;
    Udp.beginPacket(STAip.c_str(), 8080);//只需对此处进行修改，需要发送的ip及端口
    Udp.write(0x00);
    Udp.write(0xff);
    Udp.write(0x01);
    Udp.write(0x01);
    Udp.endPacket();
    uint8_t a = 0;
    for(size_t i=0;i<counti;i=i+1440)
    {
      a = a+1;
      if(counti-i>=1440)
      {
        Udp.beginPacket(STAip.c_str(), 8080);//只需对此处进行修改，需要发送的ip及端口
        Udp.write(sbuf+i,1440);
        Udp.endPacket();
      }
      else
      {
        Udp.beginPacket(STAip.c_str(), 8080);//只需对此处进行修改，需要发送的ip及端口
        Udp.write(sbuf+i,counti-i);
        Udp.endPacket();
      }
    }
    Udp.beginPacket(STAip.c_str(), 8080);//只需对此处进行修改，需要发送的ip及端口
    Udp.write(0x01);
    Udp.write(0x01);
    Udp.write(0xff);
    Udp.write(0x00);
    Udp.endPacket();
    RxHeadState = 0;
    RxTailState = 0;
    RxCounter=0;

    if(Serial.available())
    {
      counti = Serial.available();
      Serial.readBytes(sbuf, counti);
    }
  }
}


